<template>
    <view v-if="isCalendar" class="calendar_box">
        <view v-show="!isTime" class="btn_calendar_box">
            <view class="btn_box">
                <view class="cancel" @click="cancel">取消</view>
                <view class="tab_bar_box">
                    <view class="tab_bar_item" :class="[calendarType === 'solar' ? 'activation_tab_bar' : '']"
                        @click="tabBar('solar')">公历</view>
                    <view class="tab_bar_item" :class="[calendarType === 'lunar' ? 'activation_tab_bar' : '']"
                        @click="tabBar('lunar')">农历</view>
                </view>
                <view class="confirm" @click="confirm">确认</view>
            </view>

            <picker-view :indicator-style="indicatorStyle" :value="defaultValue" @change="bindChange"
                style="width:750upx; height: 400upx;">
                <picker-view-column>
                    <view class="picker_item" v-for="item in years" :key="item.id">{{ calendarType === 'solar' ?
                        item.$cytitle
                        : item.$gytitle }}
                    </view>
                </picker-view-column>

                <picker-view-column>
                    <view class="picker_item" v-for="item in months" :key="item.id">{{ calendarType === 'solar' ?
                        item.$cmtitle
                        : item.IMonthCn }}</view>
                </picker-view-column>

                <picker-view-column>
                    <view class="picker_item" v-for="item in days" :key="item.id">{{ calendarType === 'solar' ?
                        item.$cdtitle
                        : item.IDayCn }}</view>
                </picker-view-column>

                <picker-view-column>
                    <view class="picker_item" v-for="item in hours" :key="item.idh">{{ item.$lhou }}</view>
                </picker-view-column>
                <picker-view-column>
                    <view class="picker_item" v-for="item in mins" :key="item.idm">{{ item.$lmin }}</view>
                </picker-view-column>
            </picker-view>
        </view>

        <view v-show="isTime" class="confirm_time_box">
            <view class="confirm_time_title">确认时间</view>
            <view class="input_time">请确认输入的时间是否正确</view>
            <view>
                <view class="value_box">
                    公(阳)历：{{ confirmDate.lYear }}年{{ confirmDate.cMonth }}月{{ confirmDate.cDay }}日{{ hour.$lhou }}{{
                        min.$lmin }}
                </view>
                <view class="value_box">
                    农(阴)历：{{ confirmDate.gzYear }}年{{ confirmDate.IMonthCn }}{{ confirmDate.IDayCn }}{{ hour.$lhou }}{{
                        min.$lmin }}
                </view>
            </view>

            <view class="back_correct_btn_box">
                <view class="back_edit" @click="backEdit">返回修改</view>
                <view class="correct" @click="alreadyCorrect">确认正确</view>
            </view>
        </view>
    </view>
</template>

<script>
// solar2lunar 阳转阴
// lunar2solar 阴转阳
import calendar from './js-calendar-converter/src/index';

export default {
    name: 'selectCalendar',
    data() {
        return {
            // lunar 阴历
            // solar 阳历
            calendarType: 'solar',
            defaultValue: [0, 0, 0, 0, 0],
            years: [],
            months: [],
            days: [],
            confirmDate: {},
            hours: [],
            hour: {},
            mins: [],
            min: {},
            indicatorStyle: undefined,
            dayIndex: 0,
            isTime: false,
            isCalendar: false
        }
    },

    methods: {
        // 确认正确
        alreadyCorrect() {
            let confirmDate = this.confirmDate,
                hour = this.hour,
                min = this.min,
                calendarType = this.calendarType,
                defaultValue = this.defaultValue,
                obj = {},
                resultStr = '';

            obj = Object.assign(confirmDate, hour, min);
            obj.calendarType = calendarType;
            obj.defaultValue = defaultValue;
            if (calendarType === 'solar') {
                resultStr = `${obj.$cytitle}${obj.$cmtitle}${obj.$cdtitle}`;
            } else {
                resultStr = `${obj.$gytitle}${obj.IMonthCn}${obj.IDayCn}`;
            }
            resultStr += `${obj.$lhou}${obj.$lmin}`;
            obj.result = resultStr;

            this.$emit('backData', { ...obj });

            this.isCalendar = false;
            this.isTime = false;
            this.calendarType = 'solar';
            this.confirmDate = {};
            this.defaultValue = [0, 0, 0, 0, 0];
            this.hour = {};
            this.min = {};
        },
        /**
         * 设置面板默认值/年月日时分
         * @author mj <1283077926@qq.com>
         * @license Apache-2.0
         * @param {Date} dateNow 
         * @param {number} startYear 
         * @param {number} endYear 
         * @return {undefined} undefined
         */
        getTime(dateNow, startYear, endYear) {
            let years = [],
                year = dateNow.getFullYear(),
                months = [],
                month = dateNow.getMonth() + 1,
                days = [],
                day = dateNow.getDate(),
                hours = [],
                hour = dateNow.getHours() + 1,
                mins = [],
                min = dateNow.getMinutes(),
                indexOfF = (arr, IO) => arr.indexOf(IO),
                defaultValue = [];

            for (let i = startYear; i <= endYear; i++) years.push(i);
            for (let i = 0; i < 12; i++) months.push(i + 1);
            for (let i = 0; i < 31; i++) days.push(i + 1);
            for (let i = 0; i < 24; i++) hours.push(i);
            for (let i = 0; i < 60; i++) mins.push(i);

            defaultValue = [
                indexOfF(years, year),
                indexOfF(months, month),
                indexOfF(days, day),
                indexOfF(hours, hour),
                indexOfF(mins, min)
            ];

            this.defaultValue = defaultValue;
        },
        /**
         * 打开日期选择器
         * @author mj <1283077926@qq.com>
         * @license Apache-2.0
         * @param {Date} dateNow 
         * @param {number} startYear 
         * @param {number} endYear 
         * @return {undefined} undefined
         */
        async openCalendar(info = {}, startYear, endYear) {
            let dateNow = undefined;

            if (Object.keys(info).length) {
                this.calendarType = info.calendarType;
                this.confirmDate = info;
                this.defaultValue = info.defaultValue;

                if (info.calendarType === 'solar') {
                    dateNow = new Date(info.date);
                } else if (info.calendarType === 'lunar') {
                    dateNow = new Date(info.lunarDate);
                } else {
                    dateNow = new Date();
                }
            } else {
                this.calendarType = 'solar';
                this.confirmDate = {};
                this.defaultValue = [];
                dateNow = new Date();
            }

            startYear = startYear ? startYear : 1900;
            endYear = endYear ? endYear : (new Date()).getFullYear();

            startYear = startYear < 1900 ? 1900 : startYear;
            endYear = endYear > 2100 ? 2100 : endYear;

            await this.getTime(dateNow, startYear, endYear);

            this.indicatorStyle = await `height: ${Math.round(uni.getSystemInfoSync().screenWidth / (750 / 80))}px;`;
            await this.init(startYear, endYear);
            this.isCalendar = true;
        },
        // 取消
        cancel() {
            this.isCalendar = false;
            this.calendarType = 'solar';
            this.confirmDate = {};
            this.defaultValue = [0, 0, 0, 0, 0];
            this.hour = {};
            this.min = {};
            this.$emit('backData', {});
        },
        // 返回修改
        backEdit() {
            this.isTime = false;
        },
        // 确认
        confirm() {
            let calendarType = this.calendarType,
                iVal = this.defaultValue,
                years = this.years,
                months = this.months,
                days = this.days,
                year = undefined,
                month = undefined,
                day = undefined,
                confirmDate = {},
                hours = this.hours,
                mins = this.mins;

            if (calendarType === 'solar') {
                year = years[iVal[0]].cYear;
                month = months[iVal[1]].cMonth;
                day = days[iVal[2]].cDay;

                confirmDate = calendar.solar2lunar(year, month, day);
            } else {
                year = years[iVal[0]].lYear;
                month = months[iVal[1]].lMonth;
                day = days[iVal[2]].lDay;

                confirmDate = calendar.lunar2solar(year, month, day, months[iVal[1]].isLeap);
            }

            confirmDate.id = 'idd' + parseInt(Math.random() * 10001, 10);
            confirmDate.$cytitle = confirmDate.cYear + '年';
            confirmDate.$gytitle = `${confirmDate.lYear}${confirmDate.gzYear}年`;
            confirmDate.$cmtitle = confirmDate.cMonth + '月';
            confirmDate.$cdtitle = confirmDate.cDay + '日';

            this.confirmDate = confirmDate;
            this.hour = hours[iVal[3]];
            this.min = mins[iVal[4]];
            this.isTime = true;
        },
        // 阴阳历转换选项卡二次数据处理
        async tabBarConfirm() {
            let calendarType = this.calendarType,
                iVal = this.defaultValue,
                nowDate = {},
                years = this.years,
                year = undefined,
                months = this.months,
                month = undefined,
                month1 = undefined,
                days = this.days,
                day = undefined,
                day1 = undefined,
                iny = 0,
                inm = 0,
                ind = 0;

            if (calendarType === 'solar') {
                year = years[iVal[0]].lYear;
                month1 = months[iVal[1]].lMonth;
                day1 = days[iVal[2]].lDay;

                nowDate = await calendar.lunar2solar(year, month1, day1, months[iVal[1]].isLeap);
            } else {
                year = years[iVal[0]].cYear;
                month1 = months[iVal[1]].cMonth;
                day1 = days[iVal[2]].cDay;

                nowDate = await calendar.solar2lunar(year, month1, day1);
            }

            let d = await this.getMonth(year);

            if (calendarType === 'solar') {
                iny = years.findIndex((item) => item.cYear === nowDate.cYear);
                inm = d.months.findIndex((item) => item.cMonth === nowDate.cMonth);
                ind = d.days.findIndex((item) => item.cDay === nowDate.cDay);
            } else {
                iny = years.findIndex((item) => item.lYear === nowDate.lYear);
                inm = d.months.findIndex((item) => item.IMonthCn === nowDate.IMonthCn);
                ind = d.days.findIndex((item) => item.lDay === nowDate.lDay);
            }

            if (calendarType === 'solar') {
                month = d.months[inm].cMonth;
                day = d.days[ind].cDay;

                nowDate = calendar.solar2lunar(year, month, day);
            } else {
                month = d.months[inm].lMonth;
                day = d.days[ind].lDay;

                nowDate = calendar.lunar2solar(year, month, day);
            }

            this.$set(this.defaultValue, 0, iny);
            this.$set(this.defaultValue, 1, inm);
            this.$set(this.defaultValue, 2, ind);

            this.$forceUpdate();
        },
        // 阴阳历转换选项卡
        tabBar(type) {
            if (type === this.calendarType) return false;

            this.calendarType = type;
            this.$nextTick(() => this.tabBarConfirm());
        },
        // 滑动触发
        async bindChange(event) {
            let val = event.detail.value,
                calendarType = this.calendarType,
                years = this.years,
                year = undefined;

            this.defaultValue[0] = val[0];
            this.defaultValue[1] = val[1];
            this.defaultValue[2] = val[2];
            this.defaultValue[3] = val[3];
            this.defaultValue[4] = val[4];

            year = years[val[0]][calendarType === 'solar' ? 'cYear' : 'lYear'];

            this.getMonth(year);
        },
        // 月份数据
        async getMonth(year) {
            let valArr = this.defaultValue,
                calendarType = this.calendarType,
                months = [],
                month = 1,
                isLeapMonth = calendar.leapMonth(year);

            if (calendarType === 'solar') {
                for (let i = 0; i < 12; i++) {
                    let obj = calendar.solar2lunar(year, i + 1, 1);
                    obj.id = 'idm' + i + 1;
                    obj.$cmtitle = obj.cMonth + '月';

                    months.push({ ...obj });
                }
            } else {
                for (let i = 0; i < 12; i++) {
                    let obj = {};

                    if (isLeapMonth === i + 1) {
                        obj = calendar.lunar2solar(year, i + 1, 1, false);
                        obj.id = 'idm' + i + 1;
                        months.push({ ...obj });

                        obj = calendar.lunar2solar(year, i + 1, 1, true);
                        obj.id = 'idms' + i + 1;
                        months.push({ ...obj });
                    } else {
                        obj = calendar.lunar2solar(year, i + 1, 1, false);
                        obj.id = 'idm' + i + 1;
                        months.push({ ...obj });
                    }
                }
            }

            if (calendarType === 'solar') {
                month = months[valArr[1]].cMonth;
            } else {
                month = months[valArr[1]].lMonth;
            }

            // 根据年份和月份生成日期数据
            let days = await this.getDay(year, month);

            this.months = months;

            return {
                months,
                days
            };
        },
        // 日期
        getDay(year, month) {
            let calendarType = this.calendarType,
                days = [],
                day = this.defaultValue[2],
                daysLen = 0;

            if (calendarType === 'solar') {
                for (let j = 0; j < calendar.monthDays(year, month); j++) {
                    let obj = calendar.solar2lunar(year, month, j + 1);

                    days.push({ ...obj });
                }
            } else {
                for (let j = 0; j < calendar.solarDays(year, month); j++) {
                    let obj = calendar.lunar2solar(year, month, j + 1);

                    days.push({ ...obj });
                }
            }

            days = days.map((item, i) => {
                item.id = 'idd' + i;
                item.$cytitle = item.cYear + '年';
                item.$gytitle = `${item.lYear}${item.gzYear}年`;
                item.$cmtitle = item.cMonth + '月';
                item.$cdtitle = item.cDay + '日';

                return item;
            });

            daysLen = days.length - 1;
            day = day > daysLen ? daysLen : day;

            this.days = days;

            return days;
        },
        // 初始化
        async init(startYear, endYear) {
            let calendarType = this.calendarType,
                years = [],
                year = undefined,
                hoursArr = [],
                hours = [],
                mins = [],
                valArr = [],
                nowDate = {},
                Zhi = calendar.Zhi;

            for (let i = 0; i < Zhi.length; i++) {
                let item = Zhi[i];

                for (let j = 0; j < 2; j++) hoursArr.push(item);
            }

            hoursArr.push(hoursArr.splice(0, 1)[0]);
            hoursArr.unshift('未知时辰');
            hoursArr = hoursArr.splice(0);

            // 生成年份
            for (let i = startYear; i <= endYear; i++) {
                let obj = calendar.solar2lunar(i, 5, 1);
                obj.id = 'idy' + i;
                obj.$cytitle = obj.cYear + '年';
                obj.$gytitle = `${obj.lYear}${obj.gzYear}年`;

                years.push({ ...obj });
            }

            if (this.confirmDate.defaultValue) {
                valArr = [...this.confirmDate.defaultValue];
            } else {
                valArr = [...this.defaultValue];
            }

            year = years[valArr[0]][calendarType === 'solar' ? 'cYear' : 'lYear'];

            // --------------------------
            // 根据年份获取月份
            await this.getMonth(year);

            // --------------------------
            // 时辰数据
            for (let i = 0; i < 25; i++) hours.push({
                idh: `id_${i + 1}`,
                $lhou: i !== 0 ? (i - 1) + hoursArr[i] : hoursArr[i],
                $chou: i - 1,
                $gzhou: hoursArr[i]
            });

            // 分钟数据
            for (let i = 0; i < 60; i++) mins.push({
                idm: `id_${i + 1}`,
                $lmin: i + '分',
                $cmin: i,
                $gzmin: ''
            });

            this.defaultValue = valArr;
            this.years = years;
            this.hours = hours;
            this.mins = mins;
            this.hour = this.hours[valArr[3]];
            this.min = this.mins[valArr[4]];
            this.nowDate = nowDate;
        }
    }
}
</script>

<style>
.calendar_box {
    position: fixed;
    left: 0;
    top: 0;
    width: 100vw;
    height: calc(100vh - 58px);
    display: flex;
    flex-direction: column-reverse;
    background-color: rgba(200, 200, 200, .8);
    z-index: 6;
}

.btn_calendar_box {
    background-color: #ffffff;
    padding-top: 12upx;
    padding-bottom: 12upx;
    z-index: 7;
}

.btn_box {
    padding: 8upx 16upx;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.tab_bar_box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border: 1upx solid rgb(201, 23, 35);
    border-radius: 10upx;
}

.tab_bar_item {
    height: 40upx;
    line-height: 40upx;
    padding: 10upx 30upx;
    color: rgb(201, 23, 35);
    cursor: pointer;
}

.activation_tab_bar {
    background: rgb(201, 23, 35);
    color: #FFFFFF;
}

.cancel {
    color: rgb(153, 153, 153);
    cursor: pointer;
    font-size: 32upx;
}

.confirm {
    color: rgb(201, 23, 35);
    cursor: pointer;
    font-size: 32upx;
}

.picker_item {
    height: 80upx;
    line-height: 80upx;
    text-align: center;
    font-size: 28upx;
}

/* ------------------------------- */
.confirm_time_box {
    background-color: #ffffff;
    padding-top: 12upx;
    padding-bottom: 12upx;
    z-index: 7;
}

.confirm_time_title {
    text-align: center;
    color: rgb(201, 23, 35);
    font-size: 32upx;
    border-bottom: 1upx solid #E8E8E8;
    height: 88upx;
    line-height: 88upx;
}

.input_time {
    text-align: center;
    font-size: 34upx;
    color: #000000;
    height: 48upx;
    line-height: 48upx;
    margin-top: 48upx;
    padding-bottom: 20upx;
}

.value_box {
    text-align: center;
    font-size: 34upx;
    color: rgb(163, 30, 26);
    height: 34upx;
    line-height: 34upx;
    padding: 10upx 0px;
}

.back_correct_btn_box {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 40upx 0;
    color: #ffffff;
}

.back_edit {
    padding: 20upx 40upx;
    border-radius: 10upx;
    background-color: #DDDDDD;
}

.correct {
    padding: 20upx 40upx;
    margin-left: 40upx;
    border-radius: 10upx;
    background-color: rgb(163, 30, 26);
}
</style>